討論邏輯運算子(logical operators)與位元運算子(bitwise operators)的使用情境
Part I. logical operators
Part II. bitwise operators (1)
Part II. bitwise operators (2)
Part II. bitwise operators (3)
實例 1: RGB的操作
我們在進行網站開發時,有時候會需要操作到色碼,例如想從 0xEEB422 中分別抓出 RGB,這要怎麼做呢?
最基本的做法可以用substr,但看起來就不太漂亮... (雖然漂亮也不能當飯吃啦)
如果不想用字串的方式去處理,那可以考慮一下利用位元運算子去轉換,首先,我們先把色碼轉換成2位元看一下:
0xEEB422 = 1110 1110 1011 0100 0010 0010
我們要抓的 RGB 其中的 R 其實就是這組位元組中的前 8 位、G 就是中間 8 位、B就是最後的 8 位。
R = 1110 1110
G = 1011 0100
B = 0010 0010
問題是應該要怎麼抓出來呢?
首先看 R,R既然是前 8 位,那就把後面的 16 位擠掉就好了,也就是:
var color = 0xEEB422;
var r = color >> 16;
把 color 右移 16 位,不就是把右邊的 16 位給擠掉嗎?這樣就可以很輕鬆地拿到了 R。
G 是中間 8 位,那我們先把右邊的 8 位給擠掉:
var color = 0xEEB422;
var g = color >> 8;
console.log(g, g.toString(2)); // 61108 '1110111010110100'
根據我們印出來的結果,是把右邊 8 位給擠掉了,但是左邊的 R 也還在,如果想把左邊的 8 位的 R 拿掉就還需要另外處理一下:
g = g & 0xff; // 0xff = 255 --> 0000000011111111
console.log(g, g.toString(2)); // 180 '10110100'
我們用人工的方式看一下:
這邊利用了 & 的特性,& 是當兩者都是 1 的時候才會回傳 1,因為我們不想要最前面的 8 位,所以讓前面的 8 位是 0,這樣 & 出來的結果就會不見。而右邊的 8 位想要保留,因為右邊的 8 位都是 1,這樣就能保留原本右邊的 8 位。
接下來,就是最右邊的 B 了,我當時的第一個直覺反應是,能不能跟 R 一樣,很簡單的擠掉左邊的 16 位就好,結果就是:
var b = color << 16;
console.log(b, b.toString(2));
// -1272840192 '-1001011110111100000000000000000'
結果真的是非常得慘不忍睹,看來是不能採用取 R 的那招了,那取 G 的招數呢?仔細思考一下,B是要保留右邊的 8 位,也就是把前面的 16 位變成 0,於是:
var b = color & 0xff;
console.log(b, b.toString(2)); // 34 '00100010'
果然,利用跟 0 & 會變 0,跟 1 & 會變自己的特性,成功的取得了 B。
完整的函式如下:
function getRGB(color) {
var rgb = {};
rgb.r = color >> 16;
rgb.g = (color >> 8) & 0xff;
rgb.b = color & 0xff;
return rgb;
}